import PropTypes from 'ant-design-vue/es/_util/vue-types'
import {filterDictText} from '@/components/dict/JDictSelectUtil'
import {getEnhancedMixins, JVXERenderType, replaceProps} from '@/components/jeecg/JVxeTable/utils/cellUtils'

// noinspection JSUnusedLocalSymbols
export default {
    inject: {
        getParentContainer: {default: () => ((node) => node.parentNode)},
    },
    props: {
        value: PropTypes.any,
        row: PropTypes.object,
        column: PropTypes.object,
        // 组件参数
        params: PropTypes.object,
        // 渲染选项
        renderOptions: PropTypes.object,
        // 渲染类型
        renderType: PropTypes.string.def('default'),
    },
    data() {
        return {
            innerValue: null,
        }
    },
    computed: {
        caseId() {
            return this.renderOptions.caseId
        },
        originColumn() {
            return this.column.own
        },
        $type() {
            return this.originColumn.$type
        },
        rows() {
            return this.params.data
        },
        fullDataLength() {
            return this.params.$table.tableFullData.length
        },
        rowIndex() {
            return this.params.rowIndex
        },
        columnIndex() {
            return this.params.columnIndex
        },
        cellProps() {
            let {originColumn: col, renderOptions} = this

            let props = {}

            // 输入占位符
            props['placeholder'] = replaceProps(col, col.placeholder)

            // 解析props
            if (typeof col.props === 'object') {
                Object.keys(col.props).forEach(key => {
                    props[key] = replaceProps(col, col.props[key])
                })
            }

            // 判断是否是禁用的列
            props['disabled'] = (typeof col['disabled'] === 'boolean' ? col['disabled'] : props['disabled'])

            // TODO 判断是否是禁用的行
            // if (props['disabled'] !== true) {
            //   props['disabled'] = ((this.disabledRowIds || []).indexOf(row.id) !== -1)
            // }

            // 判断是否禁用所有组件
            if (renderOptions.disabled === true) {
                props['disabled'] = true
            }

            // update-begin-author:taoyan date:20211011 for: online表单，附表用户选择器{"multiSelect":false}不生效，单表可以生效 #3036
            let jsonStr = col['fieldExtendJson']
            if (jsonStr) {
                let fieldExtendJson = JSON.parse(jsonStr)
                if (fieldExtendJson && fieldExtendJson['multiSelect'] == false) {
                    props['multi'] = false
                }
            }
            // update-end-author:taoyan date:20211011 for: online表单，附表用户选择器{"multiSelect":false}不生效，单表可以生效 #3036

            return props
        },
    },
    watch: {
        $type: {
            immediate: true,
            handler($type) {
                this.enhanced = getEnhancedMixins($type)
                this.listeners = getListeners.call(this)
            },
        },
        value: {
            immediate: true,
            handler(val) {
                let value = val

                // 验证值格式
                let originValue = this.row[this.column.property]
                let getValue = this.enhanced.getValue.call(this, originValue)
                if (originValue !== getValue) {
                    // 值格式不正确，重新赋值
                    value = getValue
                    vModel.call(this, value)
                }

                this.innerValue = this.enhanced.setValue.call(this, value)

                // 判断是否启用翻译
                if (this.renderType === JVXERenderType.spaner && this.enhanced.translate.enabled) {
                    let res = this.enhanced.translate.handler.call(this, value)
                    // 异步翻译，目前仅【多级联动】使用
                    if (res instanceof Promise) {
                        res.then(value => this.innerValue = value)
                    } else {
                        this.innerValue = res
                    }
                }
            },
        },
    },
    created() {
    },
    methods: {

        /** 通用处理change事件 */
        handleChangeCommon(value) {
            let handle = this.enhanced.getValue.call(this, value)
            this.trigger('change', {value: handle})
            // 触发valueChange事件
            this.parentTrigger('valueChange', {
                type: this.$type,
                value: handle,
                oldValue: this.value,
                col: this.originColumn,
                rowIndex: this.params.rowIndex,
                columnIndex: this.params.columnIndex,
            })
        },
        /** 通用处理blur事件 */
        handleBlurCommon(value) {
            this.trigger('blur', {value})
        },

        /**
         *  如果事件存在的话，就触发
         * @param name 事件名
         * @param event 事件参数
         * @param args 其他附带参数
         */
        trigger(name, event, args = []) {
            let listener = this.listeners[name]
            if (typeof listener === 'function') {
                if (typeof event === 'object') {
                    event = this.packageEvent(name, event)
                }
                listener(event, ...args)
            }
        },
        parentTrigger(name, event, args = []) {
            args.unshift(this.packageEvent(name, event))
            this.trigger('trigger', name, args)
        },
        packageEvent(name, event = {}) {
            event.row = this.row
            event.column = this.column
            //online增强参数兼容
            event.column['key'] = this.column['property']
            event.cellTarget = this
            if (!event.type) {
                event.type = name
            }
            if (!event.cellType) {
                event.cellType = this.$type
            }
            // 是否校验表单，默认为true
            if (typeof event.validate !== 'boolean') {
                event.validate = true
            }
            return event
        },

    },
    model: {
        prop: 'value',
        event: 'change'
    },
    /**
     * 【自定义增强】用于实现一些增强事件
     * 【注】这里只是定义接口，具体功能需要到各个组件内实现（也有部分功能实现）
     * 【注】该属性不是Vue官方属性，是JVxeTable组件自定义的
     *      所以方法内的 this 指向并不是当前组件，而是方法自身，
     *      也就是说并不能 this 打点调实例里的任何方法
     */
    enhanced: {
        // 注册参数（详见：https://xuliangzhan_admin.gitee.io/vxe-table/#/table/renderer/edit）
        installOptions: {
            // 自动聚焦的 class 类名
            autofocus: '',
        },
        // 事件拦截器（用于兼容）
        interceptor: {
            // 已实现：event.clearActived
            // 说明：比如点击了某个组件的弹出层面板之后，此时被激活单元格不应该被自动关闭，通过返回 false 可以阻止默认的行为。
            ['event.clearActived'](params, event, target) {
                return true
            },
            // 自定义：event.clearActived.className
            // 说明：比原生的多了一个参数：className，用于判断点击的元素的样式名（递归到顶层）
            ['event.clearActived.className'](params, event, target) {
                return true
            },
        },
        // 【功能开关】
        switches: {
            // 是否使用 editRender 模式（仅当前组件，并非全局）
            // 如果设为true，则表头上方会出现一个可编辑的图标
            editRender: true,
            // false = 组件触发后可视）；true = 组件一直可视
            visible: false,
        },
        // 【切面增强】切面事件处理，一般在某些方法执行后同步执行
        aopEvents: {
            // 单元格被激活编辑时会触发该事件
            editActived() {
            },
            // 单元格编辑状态下被关闭时会触发该事件
            editClosed() {
            },
        },
        // 【翻译增强】可以实现例如select组件保存的value，但是span模式下需要显示成text
        translate: {
            // 是否启用翻译
            enabled: false,
            /**
             * 【翻译处理方法】如果handler留空，则使用默认的翻译方法
             * (this指向当前组件)
             *
             * @param value 需要翻译的值
             * @returns{*} 返回翻译后的数据
             */
            handler(value,) {
                // 默认翻译方法
                return filterDictText(this.column.own.options, value)
            },
        },
        /**
         * 【获取值增强】组件抛出的值
         * (this指向当前组件)
         *
         * @param value 保存到数据库里的值
         * @returns{*} 返回处理后的值
         */
        getValue(value) {
            return value
        },
        /**
         * 【设置值增强】设置给组件的值
         * (this指向当前组件)
         *
         * @param value 组件触发的值
         * @returns{*} 返回处理后的值
         */
        setValue(value) {
            return value
        },
        /**
         * 【新增行增强】在用户点击新增时触发的事件，返回新行的默认值
         *
         * @param row 行数据
         * @param column 列配置，.own 是用户配置的参数
         * @param $table vxe 实例
         * @param renderOptions 渲染选项
         * @param params 可以在这里获取 $table
         *
         * @returns 返回新值
         */
        createValue({row, column, $table, renderOptions, params}) {
            return column.own.defaultValue
        },
    }
}

function getListeners() {
    let listeners = Object.assign({}, (this.renderOptions.listeners || {}))
    if (!listeners.change) {
        listeners.change = async (event) => {
            vModel.call(this, event.value)
            await this.$nextTick()
            // 处理 change 事件相关逻辑（例如校验）
            this.params.$table.updateStatus(this.params)
        }
    }
    return listeners
}

export function vModel(value, row, property) {
    if (!row) {
        row = this.row
    }
    if (!property) {
        property = this.column.property
    }
    this.$set(row, property, value)
}

/** 模拟触发事件 */
export function dispatchEvent({cell, $event}, className, handler) {
    // alwaysEdit 下不模拟触发事件，否者会导致触发两次
    if (this && this.alwaysEdit) {
        return
    }
    window.setTimeout(() => {
        let element = cell.getElementsByClassName(className)
        if (element && element.length > 0) {
            if (typeof handler === 'function') {
                handler(element[0])
            } else {
                // 模拟触发点击事件
                if ($event) {
                    element[0].dispatchEvent($event)
                }
            }
        }
    }, 10)
}